package com.young.sso.Service.impl;


import com.young.sso.Service.UserService;
import com.young.sso.common.ExceptionCode;
import com.young.sso.entity.User;
import com.young.sso.entity.UserGold;
import com.young.sso.exception.BusinessException;

import com.young.sso.repository.UserGoldRepository;
import com.young.sso.repository.UserRepository;
import com.young.sso.util.JsonUtil;
import com.young.sso.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 用户一键登录或注册的实现类
 *
 * @author young
 * @date 2021/11/30 9:28
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class UserServiceImpl implements UserService {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private UserRepository userRepository;


    @Autowired
    private UserGoldRepository userGoldRepository;


    /**
     * 设置token前缀,防止被黑客抓包得到token
     */
    public static final String LOGIN = "#Zui-Hou-De-Jue-Chang=";


    @Override
    public Map<String, Object> login(String phone, String code) throws BusinessException {

        if (!StringUtils.isPhoneNumber(phone) || StringUtils.isEmpty(phone)) {
            throw new BusinessException(ExceptionCode.PHONE_NUMBER_IS_WRONG);
        }

        //一键登录
        //1.获取redis服务器存储的验证码
        //验证码失效的判断,如果为空则抛出异常
        Object o = redisTemplate.opsForValue().get(SmsServiceImpl.LOGIN_SMS + phone);
        if (o == null) {
            throw new BusinessException(ExceptionCode.CODE_WRONG);
        }
        String redisCode = o.toString();
        if (!redisCode.equals(code)) {
            throw new BusinessException(ExceptionCode.WRONG_CODE);
        }        // 删除验证码,根据业务判断是否需要主动删除
        redisTemplate.delete(SmsServiceImpl.LOGIN_SMS + phone);

        //校验完成, 从mysql数据库中查找用户信息,通过手机号查询用户是否存在
        User findUser = userRepository.findByPhoneEquals(phone);

        //如果用户不存在, 则匿名注册,匿名格式: "用户:"+phone , 并指定用户状态
        if (findUser == null) {
            findUser = new User();
            //        设置默认头像
            findUser.setIcon("http://bucket-lijianmin.oss-cn-chengdu.aliyuncs.com/wisdomShopping/uploadImg/0d77cd8f62064a89b4e8bb5d9d6c10c7.jpg");
//             添加字段属性
            findUser.setName("用户" + phone);
            findUser.setPhone(phone);
//            设定新用户密码为手机号后6位
            findUser.setPwd(phone.substring(5));

        }

        //如果用户存在,获取上次的token,如果不为空移除redis中上一次的登录信息
        //处理登录

//        最近一次登录时间更新
        findUser.setLastTime(new Date());
        findUser.setRegTime(new Date());
        //生成token，存储登录信息(json),利用处理后的UUID
        String token = UUID.randomUUID().toString().replace("-", "");
//      记录token到数据库
        findUser.setToken(token);
//将设置好的用户信息执行添加/更新
        userRepository.save(findUser);
        UserGold userGold = new UserGold();
        userGold.setUserId(findUser.getId());
        userGold.setNumber(new BigDecimal(0));
        userGoldRepository.save(userGold);

        String token1 = findUser.getToken();
        if (!token1.isEmpty()) {
            redisTemplate.delete(token1);
        }
        // redis添加token信息和过期时间
//        KEY:token
//        value: 用户信息json字符串
//        过期时间: 根据登录类型的不同,设置不同的过期时间

        redisTemplate.opsForValue().set(LOGIN + token, JsonUtil.objectToString(findUser), 2, TimeUnit.HOURS);
        Map<String, Object> result = new HashMap<>(1);
        result.put("token", token);
        result.put("user", findUser);
        return result;
    }

    @Override
    public Map<String, Object> loginByPassword(String phone, String password) throws BusinessException {
//      判断手机号是否合法
        if (phone == null || !StringUtils.isPhoneNumber(phone)) {
            throw new BusinessException(ExceptionCode.PHONE_NUMBER_IS_WRONG);
        }
        User byPhone = userRepository.findByPhoneEquals(phone);
//        判断是否有该用户
        if (byPhone == null) {
            throw new BusinessException(ExceptionCode.NOT_REGISTER);
        }
//        获取用户密码
        String pwd = byPhone.getPwd();
        if (!pwd.equals(password)) {
            throw new BusinessException(ExceptionCode.PASSWORD_WRONG);
        }
        String token = byPhone.getToken();
        if (!StringUtils.isEmpty(token)) {
            redisTemplate.delete(token);
        }
//        更新登录时间
        byPhone.setLastTime(new Date());
//        生成UUID 去掉空值和符号
        String replace = UUID.randomUUID().toString().replace("-", "");
//      添加新的token
        byPhone.setToken(LOGIN + replace);
//        更新用户
        userRepository.save(byPhone);


//        设置redis过期时间
        ValueOperations<String, Object> operations = redisTemplate.opsForValue();
        operations.set(LOGIN + token, JsonUtil.objectToString(byPhone), 2L, TimeUnit.MINUTES);
        Map<String, Object> result = new HashMap<>(3);
        // 放入token
        result.put("token", token);
        result.put("user", byPhone);
        return result;
    }

    @Override
    public User queryUserByToken(String token) throws BusinessException {
        ValueOperations<String, Object> stringOps = redisTemplate.opsForValue();
        Object o = stringOps.get(LOGIN + token);
        String result = null;
        if (o != null) {
            result = o.toString();
        }
        if (StringUtils.isEmpty(result)) {
            // 登录已过期，或未登录，请重新登录
            throw new BusinessException(ExceptionCode.TOKEN_FAILDE);
        }
        // 要更新失效时间
        redisTemplate.expire(LOGIN + token, 2, TimeUnit.HOURS);
        return JsonUtil.stringToObject(result, User.class);
    }

    @Override
    public void addUser(User user) throws Exception {
        try {
            System.out.println(user);
            User byPhoneEquals = userRepository.findByPhoneEquals(user.getPhone());
            if (byPhoneEquals!=null) {
                throw new BusinessException(ExceptionCode.REG_WRONG);
            }
            user.setName("用户" + user.getPhone());
            user.setRegTime(new Date());
            userRepository.save(user);
            UserGold userGold = new UserGold();
            userGold.setUserId(user.getId());
            userGold.setNumber(new BigDecimal(0));
            userGoldRepository.save(userGold);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.SEC_KILL_FAILED);
        }


    }
}
